package com.sharing.backgroundmodule.scheduledtask;

import com.sharing.aop.FunnelRateLimiterAop;
import com.sharing.backgroundmodule.service.BackstageUserHobbyService;
import com.sharing.domain.User;
import com.sharing.domain.UserHobby;
import com.sharing.domain.UserLogin;
import com.sharing.service.BrowseRecordService;
import com.sharing.service.UserLoginService;
import net.bytebuddy.agent.builder.AgentBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author MingTian
 * @version 1.0
 * @description TODO 定时任务管理器
 * @date 2023/7/6 16:45
 */
@Component
public class ScheduledTaskManager {
    @Autowired
    private BackstageUserHobbyService backstageUserHobbyService;

    @Autowired
    private UserLoginService userLoginService;

    @Autowired
    private BrowseRecordService browseRecordService;

    /**
     * 通过用户浏览记录中不断自我的兴趣点调整，
     * 后台定时任务定时针对用户的兴趣调整去修改后台用户兴趣表中的兴趣，
     * 在首页为用户进行智能化作品推荐时，
     * 若后台已经为该用户调整了兴趣，
     * 优先推荐后台系统调整的兴趣点对应的作品，
     * 其次，推荐该用户所勾选的兴趣对应的作品，
     * 再次，推荐所关注用户今日所发布的作品（一个用户仅仅推荐一个）
     * 最后，若因为曾经浏览过的作品会通过布隆过滤器过滤掉之后作品数量不满一页，会添加最热作品补全
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void scheduledTaskModifyUserHobby() {
        // 获取今日日期
        LocalDate today = LocalDate.now();

        // 获取昨日日期
        LocalDate yesterday = today.plusDays(1);

        // 日期字符串转化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 查询昨日登录的用户id
        List<Integer> users = userLoginService.selectUserIdsByDay(yesterday.format(formatter));

        // 从昨日的浏览记录中查询昨日登陆过的用户浏览比例超过百分之50的兴趣
        List<UserHobby> userHobbies = browseRecordService.selectHotHobbyByUserIds(users, yesterday.format(formatter));

        // 在 backstage_user_hobby 中添加上述兴趣
        backstageUserHobbyService.insertHobbies(userHobbies);
    }

    /**
     * 调整 HashMap<String, FunnelRateLimiter> funnels
     * 此处调整针对的是删除操作
     *
     * 删除的原因：
     * 随着用户量和功能的不断增加，
     * 在不删除的情况下，该map中的元素越来越多
     * 因此，需要考虑对该map内元素的定期删除逻辑
     *
     * 删除的方案：
     * 基于funnels出现的最直接的原因在于控制短期同一用户对同一操作的频繁操作
     * 因此funnels中并不需要存储一段时间之前的数据
     * 考虑到FunnelRateLimiter中记录着最近一次该用户执行此操作的时间，
     * 因此可以以此为标准，删除距现时刻超过指定阈值的元素
     * 并将该业务逻辑放到定时任务中定时执行
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    public void scheduledTaskModifyFunnels() {
        // 获取 funnels 中的 keySet
        Set<String> keys = new HashSet<>(FunnelRateLimiterAop.funnels.keySet());

        // 获取当前毫秒数
        long nowTs = System.currentTimeMillis();

        // 执行删除逻辑
        for (String key : keys) {
            // 若该用户最后执行此操作的时间距现在超过五分钟即删除
            if (FunnelRateLimiterAop.funnels.get(key).getLeakingTs() + 5 * 60 * 1000 < nowTs) {
                FunnelRateLimiterAop.funnels.remove(key);
            }
        }
    }
}
